﻿using System;
using System.Collections.Generic;
using System.Data.Entity.Validation;
using System.IO;
using System.Linq;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Wicresoft.Logger;
using Wicresoft.Task.Common;
using Wicresoft.Task.Team.Entity;

namespace Wicresoft.Task.Team
{
    class Finder
    {
        VersionControlServer versionControl { get; set; }
        private string pcguid { get; set; }
        private string uri { get; set; }
        private TfsTeamProjectCollection tpc { get; set; }

        public Finder(string uri)
        {
            tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(uri));
            versionControl = tpc.GetService<VersionControlServer>();
            this.uri = uri;
            pcguid = tpc.InstanceId.ToString();
        }
        public void ToFind()
        {
            try
            {
                using (TfsAutoNotifyContext tfsDB = new TfsAutoNotifyContext())
                {
                    ProjectCollection pc = new ProjectCollection(uri, pcguid);
                    pc.Collection = uri;
                    pc.Value = pcguid;
                    if (tfsDB.ProjectCollections.Count(p => p.Collection == pc.Collection) == 0)
                    {
                        tfsDB.ProjectCollections.Add(pc);
                    }
                    else
                    {
                        var pc1 = tfsDB.ProjectCollections.First(p => p.Collection == pc.Collection);
                        string pcg = pc.Value;
                        if (!pcg.Equals(pcguid))
                        {
                            pc.Value = pcguid;
                        }
                    }
                    tfsDB.SaveChanges();
                    Shelveset[] shelveSet = versionControl.QueryShelvesets("", "");
                    SaveShelveSet(shelveSet, tfsDB);
                    DeleteShelveSetIfMoreThan(shelveSet, versionControl, 30);
                    if (tfsDB.ShelveInfoes.ToList().Count != 0)
                    {
                        if (tfsDB.ShelveInfoes.Where(p => p.IsApproved && !p.IsAlreadyCheckin && !p.IsCheckinError).ToList().Count != 0)
                        {
                            CheckInIfApproved(tfsDB.ShelveInfoes.Where(p => p.IsApproved && !p.IsAlreadyCheckin && !p.IsCheckinError).ToArray(), false, versionControl, tfsDB);
                        }

                    }
                }
            }
            catch (ArgumentNullException z)
            {
            }
            catch (Exception x)
            {
                Log.Exception("Finder Connect Error ", x);
            }
        }
        public void CheckInIfApproved(ShelveInfo[] sets, bool ifSuccessDelete, VersionControlServer server, TfsAutoNotifyContext tfsDB)
        {
            try
            {
                if (sets.Length != 0)
                {
                    foreach (var item in sets)
                    {
                        string name = item.Name;
                        string owner = item.OwnerName;
                        ShelvesetCheckInParameters checkin = new ShelvesetCheckInParameters(name, owner);
                        checkin.DeleteShelveset = ifSuccessDelete;
                        try
                        {
                            int changeSetId = server.CheckInShelveset(checkin);
                            if (changeSetId > 0)
                            {
                                SaveChangeSetAndNotifyAll(changeSetId, item, server, tfsDB);
                            }
                            else
                            {
                                throw new Exception("This is a Error .Achieve the Changeset Id Error ");
                            }
                            item.IsAlreadyCheckin = true;
                        }
                        catch (CheckinException e)
                        {
                            ReportCheckInError(item, tfsDB, e);
                            continue;
                        }
                        catch (Exception x)
                        {
                            ReportCheckInError(item, tfsDB, x);
                            continue;
                        }
                    }
                }
                tfsDB.SaveChanges();
            }
            catch (Exception x)
            {

            }
        }
        //保存ChangeSet and通知所有人。
        public void SaveChangeSetAndNotifyAll(int changeSetId, ShelveInfo shelve, VersionControlServer server, TfsAutoNotifyContext tfsDB)
        {

            Changeset change = server.GetChangeset(changeSetId);
            int shelveId = tfsDB.ShelveInfoes.First(p => p.Name == shelve.Name && p.OwnerName == shelve.OwnerName && p.CreationDate == shelve.CreationDate).ShelvesetId;
            if (change != null)
            {
                tfsDB.ChangesetInfoes.Add(
                    new ChangesetInfo
                    {
                        ChangeSetId = change.ChangesetId,
                        Comment = change.Comment,
                        Committer = change.Committer,
                        CreationDate = change.CreationDate,
                        Owner = change.Owner,
                        ShelvesetId = shelveId
                    }
                    );
                tfsDB.SaveChanges();
            }
            string Bod = Helper.ReadFile("ChangeSet.html");
            string changeList = Helper.ReturnChangeListInfo(tfsDB.ChangeListInfoes.Where(p => p.ShelvesetId == shelveId).ToArray());
            string workitem = Helper.ReturnWorkItemInfo(tfsDB.WorkItemInfoes.Where(p => p.ShelvesetId == shelveId).ToArray(), tfsDB, shelve);
            string Body = string.Format(Bod, shelve.Name, change.CreationDate, change.Owner, change.Committer, workitem, shelve.Comment, changeList);
            var eList = tfsDB.EmployeesInfoes.Where(p => true).ToArray();
            List<string> emailList = new List<string>();
            foreach (var item in eList)
            {
                emailList.Add(item.Email);
            }
            SmtpHelper.SendEmail("There Are Some Changes In The Server", Body, "noreply@ws-fs-01.local", emailList.ToArray());
        }
        //当系统自动Check in 出错时 Handler
        public void ReportCheckInError(ShelveInfo item, TfsAutoNotifyContext tfsDB, Exception e)
        {
            string errorBody = Helper.ReadFile("CheckInError.html");
            string body = string.Format(errorBody, "Miles", item.Name, item.OwnerName, "在系统自动 Check In 时出错。请查看！", e.Message);
            SmtpHelper.SendEmail("自动 Check In 出错", body, "noreply@ws-fs-01.local", "milesch@wicresoft.com");
            Employee y = tfsDB.EmployeesInfoes.First(p => item.OwnerName.Contains(p.Alias));
            string ebody = string.Format(errorBody, y.EnglishName, item.Name, item.OwnerName, "您的这个打包已通过申请，但在系统自动 Check In 时出错。请手动Check In。", e.Message);
            SmtpHelper.SendEmail("自动 Check In 出错", ebody, "noreply@ws-fs-01.local", y.Email);
            ShelveInfo shelve = tfsDB.ShelveInfoes.First(p => p.Name == item.Name && p.OwnerName == item.OwnerName && p.CreationDate == p.CreationDate);
            shelve.IsCheckinError = true;
            tfsDB.SaveChanges();
        }
        public void DeleteShelveSetIfMoreThan(Shelveset[] sets, VersionControlServer server, int timeDay)
        {
            foreach (Shelveset s in sets)
            {
                DateTime x = System.DateTime.Now.AddDays(-timeDay);
                if (s.CreationDate <= x)
                {
                    server.DeleteShelveset(s);
                }
            }
        }
        public void SaveShelveSet(Shelveset[] sets, TfsAutoNotifyContext tfsDB)
        {
            try
            {
                if (sets.Length != 0)
                {
                    foreach (Shelveset s in sets)
                    {
                        if (tfsDB.ShelveInfoes == null)
                        {
                            ShelveInfo shelve = CreateShelveInfo(s, tfsDB);
                            if (shelve != null)
                            {
                                tfsDB.ShelveInfoes.Add(shelve);
                                tfsDB.SaveChanges();
                                SaveWorkItemAndChangeset(shelve, s, tfsDB);
                            }
                        }
                        else
                        {
                            if (!IsExist(s.Name, s.OwnerName, s.CreationDate, tfsDB))
                            {
                                ShelveInfo shelve = CreateShelveInfo(s, tfsDB);
                                if (shelve != null)
                                {
                                    tfsDB.ShelveInfoes.Add(shelve);
                                    tfsDB.SaveChanges();
                                    ShelveInfo x = tfsDB.ShelveInfoes.First(p => p.Name == shelve.Name && p.CreationDate == shelve.CreationDate && p.OwnerName == shelve.OwnerName);
                                    SaveWorkItemAndChangeset(x, s, tfsDB);
                                }
                            }

                        }
                        tfsDB.SaveChanges();
                    }
                }
            }
            catch (ArgumentNullException y)
            {
                Log.Exception("ArgumentNullException", y);
            }
            catch (DbEntityValidationException x)
            {
                Log.Info("DbEntityValidationException", x.InnerException + x.Message + x.EntityValidationErrors + x.Source);
            }
            catch (Exception z)
            {
                Log.Exception("SaveShelveSet", z);
            }

        }
        public void SaveWorkItemAndChangeset(ShelveInfo shelveInfo, Shelveset shelveset, TfsAutoNotifyContext tfsDB)
        {
            foreach (var item in CreateChangeList(shelveset))
            {
                try
                {
                    tfsDB.ChangeListInfoes.Add(
                        new ChangeListInfo()
                        {
                            ChangeType = item.ChangeType,
                            FileName = item.FileName,
                            ShelvesetId = shelveInfo.ShelvesetId,
                            LocalOrServerFolder = item.LocalOrServerFolder
                        }
                        );
                    tfsDB.SaveChanges();
                }
                catch (DbEntityValidationException e)
                {
                    Log.Info(item.FileName.ToString(), item.LocalOrServerFolder);
                }
            }
            foreach (var item in CreateWorkItemList(shelveset))
            {
                try
                {
                    tfsDB.WorkItemInfoes.Add(
                new WorkItemInfo()
                {
                    ShelvesetId = shelveInfo.ShelvesetId,
                    Title = item.Title,
                    WorkItemId = item.WorkItemId
                }
                );
                    tfsDB.SaveChanges();
                }
                catch (DbEntityValidationException e)
                {
                    Log.Info(item.WorkItemId.ToString(), item.Title);
                }

            }
        }
        public ShelveInfo CreateShelveInfo(Shelveset s, TfsAutoNotifyContext tfsDB)
        {
            ShelveInfo shelve = new ShelveInfo();
            string codeReviewer = s.CheckinNote.Values.First(p => p.Name == "Code Reviewer").Value;
            string comment = (s.Comment == null) ? "Unwrite" : s.Comment;
            shelve.Name = s.Name;
            shelve.OwnerName = s.OwnerName;
            shelve.CreationDate = s.CreationDate;
            shelve.Comment = (s.Comment == null) ? "Unwrite" : s.Comment; ;
            shelve.CodeReviewer = codeReviewer;
            shelve.IsApproved = false;
            shelve.CreatedTime = DateTime.Now;
            shelve.ProjectCollectionId = tfsDB.ProjectCollections.First(p => p.Collection == this.uri).ProjectCollectionId;
            if (codeReviewer.Trim().Length == 0)
            {
                shelve.IsCheck = true;
            }
            else
            {
                shelve.IsCheck = false;
            }
            return shelve;
        }
        public WorkItemInfo[] CreateWorkItemList(Shelveset s)
        {

            int i = s.WorkItemInfo.Count();
            WorkItemInfo[] WorkItemSets;
            if (i == 0)
            {
                WorkItemSets = new WorkItemInfo[i + 1];
                WorkItemSets[0] = new WorkItemInfo
                {
                    Title = "UnTouched",
                    WorkItemId = -1
                };
            }
            else
            {
                WorkItemSets = new WorkItemInfo[i];
                for (int j = 0; j < i; j++)
                {
                    var _y = s.WorkItemInfo[j].WorkItem;
                    try
                    {
                        WorkItemSets[j] = new WorkItemInfo
                        {
                            WorkItemId = _y.Id,
                            Title = _y.Title
                        };
                    }
                    catch (DbEntityValidationException e)
                    {
                        Log.Info(_y.Id.ToString(), _y.Title);
                    }
                }
            }
            return WorkItemSets;

        }
        public ChangeListInfo[] CreateChangeList(Shelveset s)
        {
            var _x = versionControl.QueryShelvedChanges(s);
            int i = _x.First().PendingChanges.Count();
            ChangeListInfo[] changSets;
            if (i == 0)
            {
                changSets = new ChangeListInfo[i + 1];
                changSets[0] = new ChangeListInfo { FileName = "UnChanged" };
            }
            else
            {
                changSets = new ChangeListInfo[i];
                for (int j = 0; j < i; j++)
                {
                    var _y = _x.First().PendingChanges[j];

                    changSets[j] = new ChangeListInfo
                    {
                        FileName = _y.FileName,
                        ChangeType = _y.ChangeTypeName,
                        LocalOrServerFolder = _y.LocalOrServerFolder
                    };
                }
            }
            return changSets;

        }

        public bool IsExist(string info, string owner, DateTime createTime, TfsAutoNotifyContext tfsDB)
        {
            bool x = false;
            try
            {
                if (tfsDB.ShelveInfoes.ToList().Count != 0)
                {
                    if (tfsDB.ShelveInfoes.Where(p => p.Name == info && p.CreationDate == createTime && p.OwnerName == owner).ToList().Count != 0)
                    {
                        x = tfsDB.ShelveInfoes.Count(p => p.Name == info && p.CreationDate == createTime && p.OwnerName == owner) >= 1;
                    }

                }
            }
            catch (System.ArgumentNullException z)
            {

            }
            return x;
        }
    }

}

